iT邦幫忙

2026 iThome 鐵人賽

DAY 6
0

昨天學了 Label 和 Selector,今天來學 Deployment。

Day 04 我們直接跑了裸 Pod,但它有個根本問題:裸 Pod 刪掉就沒了,不會自動重建。實際部署服務的時候沒有人直接用裸 Pod,用的是 Deployment。


為什麼不用裸 Pod

裸 Pod 有兩個致命問題:

問題一:掛了不會自動重建

Pod 被刪掉或 Node 故障,這個 Pod 就消失了。沒有任何機制會幫你補回來。

問題二:沒辦法管理多個副本

你想跑 3 個 todo-api Pod 來分攤流量,裸 Pod 沒有副本的概念,你只能手動建三個名字不同的 Pod 自己管理。

Deployment 解決了這兩個問題。


Deployment 是什麼

Deployment 是一個上層資源,你告訴它「我要幾個什麼樣的 Pod」,它負責把這些 Pod 建起來,並持續確保數量和狀態符合你的描述。

Deployment
    │
    └── 管理 ReplicaSet
            │
            ├── Pod 1
            ├── Pod 2
            └── Pod 3
  • 中間多了一層 ReplicaSet,它是負責維持 Pod 副本數量的元件。Deployment 管理 ReplicaSet,ReplicaSet 管理 Pod。
  • 實際操作的時候你不會直接碰 ReplicaSet,它是 Deployment 自動建立的。

Deployment YAML 拆解

apiVersion: apps/v1
kind: Deployment
metadata:
  name: todo-api
# ┌─── ① Deployment spec:控制副本數、選擇器 ───────────────────────────────┐
spec:
  replicas: 2                    # 要幾個 Pod 副本
  selector:
    matchLabels:
      app: todo-api              # 管理有這個 Label 的 Pod
  template:                      # Pod 的模板
    metadata:
      labels:
        app: todo-api            # Pod 會帶這個 Label
#   ┌─── ② Pod spec:定義容器內容 ──────────────────────────────────┐
    spec:
      containers:
        - name: api
          image: yourname/todo-app-api:v1.0.0
          ports:
            - containerPort: 8000
          env:
            - name: DATABASE_URL
              value: "mysql+pymysql://user:password@mysql-service:3306/tododb"
#   └────────────────────────────────────────────────────────────────┘
# └───────────────────────────────────────────────────────────────────────┘

詳細說明 :

  • replicas:要維持幾個 Pod。設成 2,Deployment 就會確保隨時都有 2 個 Pod 在跑,少了自動補,多了自動刪。
  • selector.matchLabels:Deployment 用這個 Selector 找它管理的 Pod。要跟 template.metadata.labels 對得上。 (就是昨天學的 Label 和 Selector 在 Deployment 裡的實際應用 )
  • template:Pod 的模板。Deployment 建立新 Pod 的時候就是照這個模板複製的。你會發現 template 底下的結構跟裸 Pod 的 YAML 很像,只是少了 apiVersionkind
  • apiVersion: apps/v1:Deployment 屬於 apps 這個 API group,跟 Pod 的 v1 不同。

實際操作

今天目標:把 todo-api 和 todo-frontend 改用 Deployment 部署,並親眼驗證 Pod 刪掉之後會自動補回來。

Step1: 部署 todo-api

  1. /Todo-App/k8s目錄,建立 todo-api-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: todo-api
spec:
  replicas: 2
  selector:
    matchLabels:
      app: todo-api
  template:
    metadata:
      labels:
        app: todo-api
        tier: backend
    spec:
      containers:
        - name: api
          image: yourname/todo-app-api:v1.0.0
          ports:
            - containerPort: 8000
          env:
            - name: DATABASE_URL
              value: "mysql+pymysql://user:password@mysql-service:3306/tododb"
  1. 套用:
kubectl apply -f todo-api-deployment.yaml
  1. 確認狀態:
kubectl get deployments

https://ithelp.ithome.com.tw/upload/images/20260917/20183863ehYvqNwzBz.png

  • READY2/2 代表 2 個 Pod 都準備好了
  • UP-TO-DATE:已更新到最新版本的 Pod 數量
  • AVAILABLE:可以服務流量的 Pod 數量
  1. 看 Pod 列表:
kubectl get pods

https://ithelp.ithome.com.tw/upload/images/20260917/20183863MZdkzm9iWM.png

Pod 名稱格式是 <deployment名稱>-<replicaset hash>-<pod hash>,這是 Deployment 自動生成的。

Step2: 驗證自癒

  1. 手動刪掉一個 Pod,看 Deployment 是否自動補回來:
# 刪掉其中一個 Pod(名稱換成你自己的)
kubectl delete pod todo-api-69bd9b578-gkwp4

# 立刻看 Pod 列表
kubectl get pods

https://ithelp.ithome.com.tw/upload/images/20260917/20183863pg7UypBsHJ.png

Deployment 發現少了一個 Pod,立刻建了一個新的補上。這就是 Day 02 說的「自癒」在實際運作的樣子。

Step3: 調整副本數量

# 擴充到 4 個副本
kubectl scale deployment todo-api --replicas=4

# 確認
kubectl get pods

也可以直接修改 YAML 的 replicas 欄位,再 kubectl apply 一次,效果一樣。

Step4: 部署 todo-frontend

  1. 在/Todo-App/k8s目錄,建立 todo-frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: todo-frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: todo-frontend
  template:
    metadata:
      labels:
        app: todo-frontend
        tier: frontend
    spec:
      containers:
        - name: frontend
          image: yourname/todo-frontend:v1.0.0
          ports:
            - containerPort: 80
kubectl apply -f todo-frontend-deployment.yaml
kubectl get deployments

⚠️ 關於 todo-frontend 的 Error 狀態

https://ithelp.ithome.com.tw/upload/images/20260917/20183863Uk9csKL7sH.png

如果你照著操作,會發現 todo-frontend 的 Pod 一直重啟並顯示 Error

kubectl logs todo-frontend-5c8466594d-4vjvw
# nginx: [emerg] host not found in upstream "todo-api-service"

這是預期中的行為,不是你的設定有問題。

原因是 frontend 的 nginx 設定裡有 proxy_pass 指向 todo-api-service,nginx 啟動時會嘗試解析這個 DNS 名稱,但 Service 還沒建立,解析失敗就 crash 了。

等到 Day 08 建立 Service 之後,todo-api-service 的 DNS 記錄就會存在,frontend 就能正常啟動。目前先忽略這個錯誤,繼續往下學就好。

常用指令整理

# 看 Deployment 詳細狀態
kubectl describe deployment todo-api

# 確認 Deployment 是否完成更新
kubectl rollout status deployment todo-api

# 看 Deployment 歷史版本
kubectl rollout history deployment todo-api

# 刪除 Deployment(連帶刪掉底下的 Pod)
kubectl delete deployment todo-api

小結

今天學了 Deployment,它是 K8s 裡最常用的部署方式:

  • 裸 Pod 掛了不重建、沒有副本管理,不適合生產環境
  • Deployment 透過 ReplicaSet 管理 Pod,確保副本數量始終符合期望
  • 自癒:Pod 被刪掉,Deployment 自動補回來
  • 擴縮容kubectl scale 或修改 replicas,立即生效

目前 todo-api 和 todo-frontend 各自跑著 2 個 Pod,但它們之間還不能互相溝通,外面也連不進來。明天先學 Rolling Update,了解如何在不停機的情況下更新服務版本,Day 08 再用 Service 把這些 Pod 串起來。


上一篇
Day 05|Label 和 Selector
系列文
從零學 K8s|30 天核心概念 × 實作,新手也能真正掌握 Kubernetes6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言